package cn.attackme.myuploader.utils;


import cn.attackme.myuploader.model.ExcelContent;
import cn.attackme.myuploader.model.Img;
import com.spire.pdf.PdfDocument;
import com.spire.pdf.PdfPageBase;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 文件操作工具类
 */
public class FileUtils {

    /**
     * 写入文件
     *
     * @param target
     * @param src
     * @throws IOException
     */
    public static Img write(String target, InputStream src) throws IOException {
        BufferedImage sourceImg = ImageIO.read(src);
        Img img = new Img();
        img.setW(sourceImg.getWidth());
        img.setH(sourceImg.getHeight());
        File outputfile = new File(target);
        ImageIO.write(sourceImg, "png", outputfile);
        return img;
    }

    public static String uploadFile(String fileName, byte bytes[]) throws IOException {
        File filePath = new File(fileName);
        BufferedOutputStream buffStream = new BufferedOutputStream(new FileOutputStream(filePath));
        buffStream.write(bytes);
        buffStream.close();
        return filePath.getAbsolutePath();
    }

    /**
     * 分块写入文件
     *
     * @param target
     * @param targetSize
     * @param src
     * @param srcSize
     * @param chunks
     * @param chunk
     * @throws IOException
     */
    public static void writeWithBlok(String target, Long targetSize, InputStream src, Long srcSize, Integer chunks, Integer chunk) throws IOException {
        RandomAccessFile randomAccessFile = new RandomAccessFile(target, "rw");
        randomAccessFile.setLength(targetSize);
        if (chunk == chunks - 1) {
            randomAccessFile.seek(targetSize - srcSize);
        } else {
            randomAccessFile.seek(chunk * srcSize);
        }
        byte[] buf = new byte[1024];
        int len;
        while (-1 != (len = src.read(buf))) {
            randomAccessFile.write(buf, 0, len);
        }
        randomAccessFile.close();
    }

    /**
     * 生成随机文件名
     *
     * @return
     */
    public static String generateFileName() {
        return UUID.randomUUID().toString();
    }

    /**
     * 识别内容通过位置
     */
    public static ExcelContent getExcelContentByLocation(MultipartFile file) throws IOException {
        //创建PdfDocument实例
        PdfDocument doc = new PdfDocument();
        //加载PDF文件
        doc.loadFromStream(file.getInputStream());
        //选择pdf第一页
        PdfPageBase pdfPageBase = doc.getPages().get(0);

        //识别发票代码
        Rectangle code_rect = new Rectangle(420, 10, 116, 20);
        String codeContent = pdfPageBase.extractText(code_rect).replaceAll(" ", "").replaceAll("　", "");
        //识别区域正则匹配
        String p_code = "\\d{12}";
        Pattern r_code = Pattern.compile(p_code);
        Matcher m_code = r_code.matcher(codeContent);
        String code = "";
        if (m_code.find()) code = m_code.group();

        //识别发票号码
        Rectangle num_rect = new Rectangle(413, 34, 117, 18);
        String numContent = pdfPageBase.extractText(num_rect).replaceAll(" ", "").replaceAll("　", "");
        String p_num = "(\\d{8})";
        Pattern r_num = Pattern.compile(p_num);
        Matcher m_num = r_num.matcher(numContent);
        String num = "";
        if (m_num.find()) num = m_num.group();

        //发票日期
        Rectangle time_rect = new Rectangle(413, 47, 129, 20);
        String timeContent = pdfPageBase.extractText(time_rect).replaceAll(" ", "").replaceAll("　", "").replaceAll("年", "").replaceAll("月", "").replaceAll("日", "");
        String p_time = "([0-9]{8})";
        Pattern r_time = Pattern.compile(p_time);
        Matcher m_time = r_time.matcher(timeContent);
        String time = "";
        if (m_time.find()) {
            time = m_time.group();
            time = time.substring(0, 4) + "/" + time.substring(4, 6) + "/" + time.substring(6);
        }

        //校验码
        Rectangle check_rect = new Rectangle(413, 64, 170, 18);
        String checkContent = pdfPageBase.extractText(check_rect).replaceAll(" ", "").replaceAll("　", "");
        System.out.println(checkContent);
        String p_check = "(\\d{20})";
        Pattern r_check = Pattern.compile(p_check);
        Matcher m_check = r_check.matcher(checkContent);
        String check = "";
        if (m_check.find()) check = m_check.group();

        //开票方名称
        Rectangle name_rect = new Rectangle(35, 294, 290, 17);
        String nameContent = pdfPageBase.extractText(name_rect).replaceAll(" ", "").replaceAll("　", "").replace("名称:", "").replace("名称：", "");
        String p_name = "([\\u4E00-\\u9FA5]+|[a-z]+|[A-Z]+)";
        Pattern r_name = Pattern.compile(p_name);
        Matcher m_name = r_name.matcher(nameContent);
        String name = "";
        if (m_name.find()) name = m_name.group();

        //金额
        Rectangle price_rect = new Rectangle(385, 253, 95, 23);
        String priceContent = pdfPageBase.extractText(price_rect).replaceAll(" ", "").replaceAll("　", "");
        String p_price = "(\\d+\\.\\d+)";
        Pattern r_price = Pattern.compile(p_price);
        Matcher m_price = r_price.matcher(priceContent);
        String price = "0";
        if (m_price.find()) price = m_price.group();

        //税额
        Rectangle tax_rect = new Rectangle(499, 252, 86, 23);
        String taxContent = pdfPageBase.extractText(tax_rect).replaceAll(" ", "").replaceAll("　", "");
        String p_tax = "(\\d+\\.\\d+)";
        Pattern r_tax = Pattern.compile(p_tax);
        Matcher m_tax = r_tax.matcher(taxContent);
        String tax = "0";
        if (m_tax.find()) tax = m_tax.group();

        //总价
        Rectangle sum_rect = new Rectangle(433, 274, 150, 20);
        String sumContent = pdfPageBase.extractText(sum_rect).replaceAll(" ", "").replaceAll("　", "");
        String p_sum = "(\\d+\\.\\d+)";
        Pattern r_sum = Pattern.compile(p_sum);
        Matcher m_sum = r_sum.matcher(sumContent);
        String sum = "0";
        if (m_sum.find()) sum = m_sum.group();
        return new ExcelContent(code, num, time, check, name, price, tax, sum);
    }

    /**
     * 增值税发票识别内容通过文本内容
     */
    public static ExcelContent getExcelContentByContent(MultipartFile file) throws IOException {
        //创建PdfDocument实例
        PdfDocument doc = new PdfDocument();
        //加载PDF文件
        doc.loadFromStream(file.getInputStream());
        //选择pdf第一页
        PdfPageBase pdfPageBase = doc.getPages().get(0);
        //获取pdf所有文本内容，并把空格去掉，以及冒号统一为英文字符
        String contents = pdfPageBase.extractText().replaceAll(" ","").replaceAll("　","")
                .replaceAll("：",":").replaceAll("⼩","小").replaceAll("⼤","大")
                .replaceAll("开票⽇期","开票日期").replaceAll("⽇","日");

        //识别发票代码
        String p_code = "发票代码:\\d{12}";
        Pattern r_code = Pattern.compile(p_code);
        Matcher m_code = r_code.matcher(contents);
        String code = "";
        if (m_code.find()) code = m_code.group().replaceAll("发票代码:", "");

        //识别发票号码
        String p_num = "(发票号码:\\d{8})";
        Pattern r_num = Pattern.compile(p_num);
        Matcher m_num = r_num.matcher(contents);
        String num = "";
        if (m_num.find()) num = m_num.group().replaceAll("发票号码:", "");

        //发票日期
        String p_time = "(开票日期:\\d{4}年\\d{2}月\\d{2}日)|(开票日期:[0-9]{8})|(开票日期:\\d{4}\\-\\d{2}\\-\\d{2})|(开票日期:\\d{4}/\\d{2}/\\d{2})" +
                "|(开票日期:.*年.*月.*日.*)";
        Pattern r_time = Pattern.compile(p_time);
        Matcher m_time = r_time.matcher(contents);
        String time = "";
        if (m_time.find()) {
            time = m_time.group().replaceAll("开票日期:", "").replaceAll("年", "").replaceAll("月", "")
                    .replaceAll("日", "").replaceAll("-", "").replaceAll("/", "");
            time = time.substring(0, 4) + "/" + time.substring(4, 6) + "/" + time.substring(6);
        }

        //校验码
        String p_check = "(校验码:\\d{20})";
        Pattern r_check = Pattern.compile(p_check);
        Matcher m_check = r_check.matcher(contents);
        String check = "";
        if (m_check.find()) check = m_check.group().replaceAll("校验码:", "");

        //开票方名称
        String nameContent = pdfPageBase.extractText(new Rectangle(30, 290, 290, 150)).replaceAll(" ", "").replaceAll("　", "").replaceAll("：", ":");
        String p_name = "(名称:.*)";
        Pattern r_name = Pattern.compile(p_name);
        Matcher m_name = r_name.matcher(nameContent);
        String name = "";
        if (m_name.find()) name = m_name.group().replaceAll("名称:", "");

        //金额
        String p_price = "(合计)([¥]|[￥])(\\d+\\.\\d+)";
        Pattern r_price = Pattern.compile(p_price);
        Matcher m_price = r_price.matcher(contents);
        String price = "0";
        if (m_price.find()) price = m_price.group().replaceAll("合计", "").replaceAll("¥", "").replaceAll("￥", "");

        //税额
        String tax = "0";
        for (String line : contents.split("\\n")) {
            if (line.contains(m_price.group(0))) {
                String taxstr = line.replace(m_price.group(0), "");
                String p_tax = "([¥]|[￥])(\\d+\\.\\d+)";
                Pattern r_tax = Pattern.compile(p_tax);
                Matcher m_tax = r_tax.matcher(taxstr);
                if (m_tax.find()) tax = m_tax.group().replaceAll("¥", "").replaceAll("￥", "");
                break;
            }
        }


        //总价
        String p_sum = "([（]|[(])(小写)([）]|[)])([¥]|[￥])(\\d+\\.\\d+)";
        Pattern r_sum = Pattern.compile(p_sum);
        Matcher m_sum = r_sum.matcher(contents);
        String sum = "0";
        if (m_sum.find()) sum = m_sum.group().replaceAll("小写", "").replaceAll("\\(", "").replaceAll("（", "")
                .replaceAll("）", "").replaceAll("\\)", "").replaceAll("¥", "").replaceAll("￥", "");
        return new ExcelContent(code, num, time, check, name, price, tax, sum);
    }

    /**
     * 非税收票据识别内容通过文本内容
     */
    public static ExcelContent getExcelContentByContent2(MultipartFile file) throws IOException {
        //创建PdfDocument实例
        PdfDocument doc = new PdfDocument();
        //加载PDF文件
        doc.loadFromStream(file.getInputStream());
        //选择pdf第一页
        PdfPageBase pdfPageBase = doc.getPages().get(0);
        //获取pdf所有文本内容，并把空格去掉，以及冒号统一为英文字符
        String contents = pdfPageBase.extractText().replaceAll(" ","").replaceAll("　","")
                .replaceAll("：",":").replaceAll("⼩","小").replaceAll("⼤","大")
                .replaceAll("开票⽇期","开票日期").replaceAll("⽇","日");
        //发票代码
        String p_code = "票据代码:\\d{8}";
        Pattern r_code = Pattern.compile(p_code);
        Matcher m_code = r_code.matcher(contents);
        String code = "";
        if(m_code.find()) code = m_code.group().replaceAll("票据代码:","");
        //识别发票号码
        String p_num = "(票据号码:\\d{10})";
        Pattern r_num = Pattern.compile(p_num);
        Matcher m_num = r_num.matcher(contents);
        String num = "";
        if(m_num.find()) num = m_num.group().replaceAll("票据号码:","");


        //发票日期
        String p_time = "(开票日期:\\d{4}年\\d{2}月\\d{2}日)|(开票日期:[0-9]{8})|(开票日期:\\d{4}\\-\\d{2}\\-\\d{2})|(开票日期:\\d{4}/\\d{2}/\\d{2})" +
                "|(开票日期:.*年.*月.*日.*)";
        Pattern r_time = Pattern.compile(p_time);
        Matcher m_time = r_time.matcher(contents);
        String time = "";
        if(m_time.find()) {
            time = m_time.group().replaceAll("开票日期:","").replaceAll("年","").replaceAll("月","")
                    .replaceAll("日","").replaceAll("-","").replaceAll("/","");
            time = time.substring(0, 4) + "/" + time.substring(4, 6) + "/" + time.substring(6);

        }

        //校验码后6位
        String p_check = "(校验码:\\S{6})";
        Pattern r_check = Pattern.compile(p_check);
        Matcher m_check = r_check.matcher(contents);
        String check = "";
        if(m_check.find()) check = m_check.group().replaceAll("校验码:","");

        //开票方名称
        String name = "";
        for (String line:contents.split("\\n")) {
            if(line.contains("收款单位")){
                line = line.substring(line.indexOf(":")+1,line.indexOf(":",line.indexOf(":")+1)).replaceAll("复核人","").replaceAll("收款人","");
                name = line;
                break;
            }
        }

        //金额
        String p_price = "(([(]|[（])(小写)([)]|[）])(\\d+\\.\\d+))|(([(]|[（])(小写)([)]|[）])([¥]|[￥])(\\d+\\.\\d+))";
        Pattern r_price = Pattern.compile(p_price);
        Matcher m_price = r_price.matcher(contents);
        String price = "0";
        if(m_price.find()) price = m_price.group().replaceAll("小写","").replaceAll("\\(","").replaceAll("（","")
                    .replaceAll("）","").replaceAll("\\)","").replaceAll("¥","").replaceAll("￥","");

        //税额
        String tax = "0";

        //总价
        String sum = price;

        return new ExcelContent(code, num, time, check, name, price, tax, sum);
    }
}
